home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / mma2ltx / mma2ltx.c < prev    next >
C/C++ Source or Header  |  1994-07-15  |  30KB  |  816 lines

  1. /************************************************************************\
  2. *                                                                        *
  3. *   mma2ltc.c - Copyright (C) 1994 by Giuseppe Ghibo`                    *
  4. *                                                                        *
  5. *   version 1.2 - 16 July 1994                                           *
  6. *                                                                        *
  7. \************************************************************************/
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <math.h>
  14. #include <time.h>
  15. #include <ctype.h>
  16.  
  17. typedef int bool;
  18. #ifndef TRUE
  19. #define TRUE 1
  20. #endif
  21. #ifndef FALSE
  22. #define FALSE 0
  23. #endif
  24.  
  25. #ifndef min
  26. #define min(a,b) (a<b ? a : b)
  27. #endif
  28. #ifndef max
  29. #define max(a,b) (a>b ? a : b)
  30. #endif
  31.  
  32. struct pnts {
  33.     float gx,gy,tx,ty;
  34. };
  35.  
  36. struct scaletrasl {
  37.     float Ax,Ay,Bx,By;
  38. };
  39.  
  40. struct cw {
  41.     float ctx,wtx,cgx,wgx,cty,wty,cgy,wgy;
  42. };
  43.  
  44. struct TeXunits {
  45.     float convfactor;
  46.     char *strunit;
  47. };
  48.  
  49. struct TeXunits TeXtable[] = {
  50.   {72.0/25.4,"mm"},                     /* mm to bp */
  51.   {72.0/2.54,"cm"},                     /* cm to bp */
  52.   {72.0/72.27,"pt"},                    /* pt to bp */
  53.   {1.0,"bp"},                           /* bp to bp */
  54.   {72.0/72.27*12.0,"pc"},               /* pc to bp */
  55.   {72.0,"in"},                          /* in to bp */
  56.   {1238.0/1157.0*72.0/72.27,"dd"},      /* dd to bp */
  57.   {1238.0/1157.0*12.0*72.0/72.27,"cc"}, /* cc to bp */
  58.   {72.0/72.27/65536.0,"sp"},            /* sp to bp */
  59.   {1.0,""}
  60. };
  61.  
  62. /* Prototypes */
  63. void Mlprun(float,float,struct cw *);
  64. void Mlp(float,float,struct scaletrasl *);
  65. void Mlp1(float,float,float,float,float,float,float *,float *,bool *);
  66. float strtobp(char *);
  67. float bptounit(char *);
  68. void stripext(char *,char *);
  69. char *strtolwr(char *);
  70.  
  71. #define NMAX 1000
  72. #define NMAXFILEIN 20 /* maximun number of files to process */
  73. #define TMPLEN 512
  74. #define PROLOG "texmma22.pro"
  75. #define OPTSWITCH1 '-'
  76. #define OPTSWITCH2 '/'
  77.  
  78. int np=0;
  79. struct pnts *p;
  80. char tmpbuf1[TMPLEN],tmpbuf2[TMPLEN];
  81. char texfname[256];
  82. bool Mnodistort = TRUE;              /* keep the aspect ratio ? */
  83.  
  84. /* This is the Mathematica v2.2 prologue file */
  85. char *prologue[] = {
  86. "/Mlmarg 0 def /Mrmarg 0 def /Mbmarg 0 def /Mtmarg 0 def /Mtransform{}\n",
  87. "bind def /Mfixwid true def /Mfixdash false def /Mrot 0 def /Mpstart{\n",
  88. "MathPictureStart}bind def /Mpend{MathPictureEnd}bind def /Mscale{0 1 0 1\n",
  89. "5 -1 roll MathScale}bind def /ISOLatin1Encoding dup where{pop pop}{[\n",
  90. "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n",
  91. "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n",
  92. "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n",
  93. "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n",
  94. "/space /exclam /quotedbl /numbersign /dollar /percent /ampersand\n",
  95. "/quoteright /parenleft /parenright /asterisk /plus /comma /minus /period\n",
  96. "/slash /zero /one /two /three /four /five /six /seven /eight /nine\n",
  97. "/colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F\n",
  98. "/G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n",
  99. "/backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d\n",
  100. "/e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z\n",
  101. "/braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n",
  102. "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n",
  103. "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /dotlessi /grave\n",
  104. "/acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef\n",
  105. "/ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space /exclamdown\n",
  106. "/cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n",
  107. "/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron\n",
  108. "/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph\n",
  109. "/periodcentered /cedilla /onesuperior /ordmasculine /guillemotright\n",
  110. "/onequarter /onehalf /threequarters /questiondown /Agrave /Aacute\n",
  111. "/Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute\n",
  112. "/Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth\n",
  113. "/Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n",
  114. "/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n",
  115. "/germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae\n",
  116. "/ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute\n",
  117. "/icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex\n",
  118. "/otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex\n",
  119. "/udieresis /yacute /thorn /ydieresis]def}ifelse /MFontDict 50 dict def\n",
  120. "/MStrCat{exch dup length 2 index length add string dup 3 1 roll copy\n",
  121. "length exch dup 4 2 roll exch putinterval}def /MCreateEncoding{1 index\n",
  122. "255 string cvs(-)MStrCat 1 index MStrCat cvn exch(Encoding)MStrCat cvn\n",
  123. "dup where{exch get}{pop StandardEncoding}ifelse 3 1 roll dup MFontDict\n",
  124. "exch known not{1 index findfont dup length dict begin{1 index /FID ne{\n",
  125. "def}{pop pop}ifelse}forall /Encoding 3 index def currentdict end 1 index\n",
  126. "exch definefont pop MFontDict 1 index null put}if exch pop exch pop}def\n",
  127. "/ISOLatin1{(ISOLatin1)MCreateEncoding}def /ISO8859{(ISOLatin1)\n",
  128. "MCreateEncoding}def /Mcopyfont{dup maxlength dict exch{1 index /FID eq{\n",
  129. "pop pop}{2 index 3 1 roll put}ifelse}forall}def /Plain /Courier findfont\n",
  130. "Mcopyfont definefont pop /Bold /Courier-Bold findfont Mcopyfont\n",
  131. "definefont pop /Italic /Courier-Oblique findfont Mcopyfont definefont\n",
  132. "pop /MathPictureStart{gsave Mtransform Mlmarg Mbmarg translate Mwidth\n",
  133. "Mlmarg Mrmarg add sub /Mwidth exch def Mheight Mbmarg Mtmarg add sub\n",
  134. "/Mheight exch def /Mtmatrix matrix currentmatrix def /Mgmatrix matrix\n",
  135. "currentmatrix def}bind def /MathPictureEnd{grestore}bind def /MFill{0 0\n",
  136. "moveto Mwidth 0 lineto Mwidth Mheight lineto 0 Mheight lineto fill}bind\n",
  137. "def /MPlotRegion{3 index Mwidth mul 2 index Mheight mul translate exch\n",
  138. "sub Mheight mul /Mheight exch def exch sub Mwidth mul /Mwidth exch def}\n",
  139. "bind def /MathSubStart{Momatrix Mgmatrix Mtmatrix Mwidth Mheight 7 -2\n",
  140. "roll moveto Mtmatrix setmatrix currentpoint Mgmatrix setmatrix 9 -2 roll\n",
  141. "moveto Mtmatrix setmatrix currentpoint 2 copy translate /Mtmatrix matrix\n",
  142. "currentmatrix def 3 -1 roll exch sub /Mheight exch def sub /Mwidth exch\n",
  143. "def}bind def /MathSubEnd{/Mheight exch def /Mwidth exch def /Mtmatrix\n",
  144. "exch def dup setmatrix /Mgmatrix exch def /Momatrix exch def}bind def\n",
  145. "/Mdot{moveto 0 0 rlineto stroke}bind def /Mtetra{moveto lineto lineto\n",
  146. "lineto fill}bind def /Metetra{moveto lineto lineto lineto closepath\n",
  147. "gsave fill grestore 0 setgray stroke}bind def /Mistroke{flattenpath 0 0\n",
  148. "0{4 2 roll pop pop}{4 -1 roll 2 index sub dup mul 4 -1 roll 2 index sub\n",
  149. "dup mul add sqrt 4 -1 roll add 3 1 roll}{stop}{stop}pathforall pop pop\n",
  150. "currentpoint stroke moveto currentdash 3 -1 roll add setdash}bind def\n",
  151. "/Mfstroke{stroke currentdash pop 0 setdash}bind def /Mrotsboxa{gsave dup\n",
  152. "/Mrot exch def Mrotcheck Mtmatrix dup setmatrix 7 1 roll 4 index 4 index\n",
  153. "translate rotate 3 index -1 mul 3 index -1 mul translate /Mtmatrix\n",
  154. "matrix currentmatrix def grestore Msboxa 3 -1 roll /Mtmatrix exch def\n",
  155. "/Mrot 0 def}bind def /Msboxa{newpath 5 -1 roll Mvboxa pop Mboxout 6 -1\n",
  156. "roll 5 -1 roll 4 -1 roll Msboxa1 5 -3 roll Msboxa1 Mboxrot[7 -2 roll 2\n",
  157. "copy[3 1 roll 10 -1 roll 9 -1 roll]6 1 roll 5 -2 roll]}bind def /Msboxa1\n",
  158. "{sub 2 div dup 2 index 1 add mul 3 -1 roll -1 add 3 -1 roll mul}bind def\n",
  159. "/Mvboxa{Mfixwid{Mvboxa1}{dup Mwidthcal 0 exch{add}forall exch Mvboxa1 4\n",
  160. "index 7 -1 roll add 4 -1 roll pop 3 1 roll}ifelse}bind def /Mvboxa1{\n",
  161. "gsave newpath[true 3 -1 roll{Mbbox 5 -1 roll{0 5 1 roll}{7 -1 roll exch\n",
  162. "sub(m)stringwidth pop .3 mul sub 7 1 roll 6 -1 roll 4 -1 roll Mmin 3 -1\n",
  163. "roll 5 index add 5 -1 roll 4 -1 roll Mmax 4 -1 roll}ifelse false}forall{\n",
  164. "stop}if counttomark 1 add 4 roll]grestore}bind def /Mbbox{1 dict begin 0\n",
  165. "0 moveto /temp(T)def{gsave currentpoint newpath moveto temp 0 3 -1 roll\n",
  166. "put temp false charpath flattenpath currentpoint pathbbox grestore\n",
  167. "moveto lineto moveto}forall pathbbox newpath end}bind def /Mmin{2 copy\n",
  168. "gt{exch}if pop}bind def /Mmax{2 copy lt{exch}if pop}bind def /Mrotshowa{\n",
  169. "dup /Mrot exch def Mrotcheck Mtmatrix dup setmatrix 7 1 roll 4 index 4\n",
  170. "index translate rotate 3 index -1 mul 3 index -1 mul translate /Mtmatrix\n",
  171. "matrix currentmatrix def Mgmatrix setmatrix Mshowa /Mtmatrix exch def\n",
  172. "/Mrot 0 def}bind def /Mshowa{4 -2 roll moveto 2 index Mtmatrix setmatrix\n",
  173. "Mvboxa 7 1 roll Mboxout 6 -1 roll 5 -1 roll 4 -1 roll Mshowa1 4 1 roll\n",
  174. "Mshowa1 rmoveto currentpoint Mfixwid{Mshowax}{Mshoway}ifelse pop pop pop\n",
  175. "pop Mgmatrix setmatrix}bind def /Mshowax{0 1 4 index length -1 add{2\n",
  176. "index 4 index 2 index get 3 index add moveto 4 index exch get Mfixdash{\n",
  177. "Mfixdashp}if show}for}bind def /Mfixdashp{dup length 1 gt 1 index true\n",
  178. "exch{45 eq and}forall and{gsave(--)stringwidth pop(-)stringwidth pop sub\n",
  179. "2 div 0 rmoveto dup length 1 sub{(-)show}repeat grestore}if}bind def\n",
  180. "/Mshoway{3 index Mwidthcal 5 1 roll 0 1 4 index length -1 add{2 index 4\n",
  181. "index 2 index get 3 index add moveto 4 index exch get[6 index aload\n",
  182. "length 2 add -1 roll{pop Strform stringwidth pop neg exch add 0 rmoveto}\n",
  183. "exch kshow cleartomark}for pop}bind def /Mwidthcal{[exch{Mwidthcal1}\n",
  184. "forall][exch dup Maxlen -1 add 0 1 3 -1 roll{[exch 2 index{1 index Mget\n",
  185. "exch}forall pop Maxget exch}for pop]Mreva}bind def /Mreva{[exch aload\n",
  186. "length -1 1{1 roll}for]}bind def /Mget{1 index length -1 add 1 index ge{\n",
  187. "get}{pop pop 0}ifelse}bind def /Maxlen{[exch{length}forall Maxget}bind\n",
  188. "def /Maxget{counttomark -1 add 1 1 3 -1 roll{pop Mmax}for exch pop}bind\n",
  189. "def /Mwidthcal1{[exch{Strform stringwidth pop}forall]}bind def /Strform{\n",
  190. "/tem(x)def tem 0 3 -1 roll put tem}bind def /Mshowa1{2 copy add 4 1 roll\n",
  191. "sub mul sub -2 div}bind def /MathScale{Mwidth Mheight Mlp translate\n",
  192. "scale /yscale exch def /ybias exch def /xscale exch def /xbias exch def\n",
  193. "/Momatrix xscale yscale matrix scale xbias ybias matrix translate matrix\n",
  194. "concatmatrix def /Mgmatrix matrix currentmatrix def}bind def /Mlp{3 copy\n",
  195. "Mlpfirst{Mnodistort{Mmin dup}if 4 index 2 index 2 index Mlprun 11 index\n",
  196. "11 -1 roll 10 -4 roll Mlp1 8 index 9 -5 roll Mlp1 4 -1 roll and{exit}if\n",
  197. "3 -1 roll pop pop}loop exch 3 1 roll 7 -3 roll pop pop pop}bind def\n",
  198. "/Mlpfirst{3 -1 roll dup length 2 copy -2 add get aload pop pop pop 4 -2\n",
  199. "roll -1 add get aload pop pop pop 6 -1 roll 3 -1 roll 5 -1 roll sub div\n",
  200. "4 1 roll exch sub div}bind def /Mlprun{2 copy 4 index 0 get dup 4 1 roll\n",
  201. "Mlprun1 3 copy 8 -2 roll 9 -1 roll{3 copy Mlprun1 3 copy 11 -3 roll /gt\n",
  202. "Mlpminmax 8 3 roll 11 -3 roll /lt Mlpminmax 8 3 roll}forall pop pop pop\n",
  203. "pop 3 1 roll pop pop aload pop 5 -1 roll aload pop exch 6 -1 roll\n",
  204. "Mlprun2 8 2 roll 4 -1 roll Mlprun2 6 2 roll 3 -1 roll Mlprun2 4 2 roll\n",
  205. "exch Mlprun2 6 2 roll}bind def /Mlprun1{aload pop exch 6 -1 roll 5 -1\n",
  206. "roll mul add 4 -2 roll mul 3 -1 roll add}bind def /Mlprun2{2 copy add 2\n",
  207. "div 3 1 roll exch sub}bind def /Mlpminmax{cvx 2 index 6 index 2 index\n",
  208. "exec{7 -3 roll 4 -1 roll}if 1 index 5 index 3 -1 roll exec{4 1 roll pop\n",
  209. "5 -1 roll aload pop pop 4 -1 roll aload pop[8 -2 roll pop 5 -2 roll pop\n",
  210. "6 -2 roll pop 5 -1 roll]4 1 roll pop}{pop pop pop}ifelse}bind def /Mlp1{\n",
  211. "5 index 3 index sub 5 index 2 index mul 1 index le 1 index 0 le or dup\n",
  212. "not{1 index 3 index div .99999 mul 8 -1 roll pop 7 1 roll}if 8 -1 roll 2\n",
  213. "div 7 -2 roll pop sub 5 index 6 -3 roll pop pop mul sub exch}bind def\n",
  214. "/intop 0 def /inrht 0 def /inflag 0 def /outflag 0 def /xadrht 0 def\n",
  215. "/xadlft 0 def /yadtop 0 def /yadbot 0 def /Minner{outflag 1 eq{/outflag\n",
  216. "0 def /intop 0 def /inrht 0 def}if 5 index gsave Mtmatrix setmatrix\n",
  217. "Mvboxa pop grestore 3 -1 roll pop dup intop gt{/intop exch def}{pop}\n",
  218. "ifelse dup inrht gt{/inrht exch def}{pop}ifelse pop /inflag 1 def}bind\n",
  219. "def /Mouter{/xadrht 0 def /xadlft 0 def /yadtop 0 def /yadbot 0 def\n",
  220. "inflag 1 eq{dup 0 lt{dup intop mul neg /yadtop exch def}if dup 0 gt{dup\n",
  221. "intop mul /yadbot exch def}if pop dup 0 lt{dup inrht mul neg /xadrht\n",
  222. "exch def}if dup 0 gt{dup inrht mul /xadlft exch def}if pop /outflag 1\n",
  223. "def}{pop pop}ifelse /inflag 0 def /inrht 0 def /intop 0 def}bind def\n",
  224. "/Mboxout{outflag 1 eq{4 -1 roll xadlft leadjust add sub 4 1 roll 3 -1\n",
  225. "roll yadbot leadjust add sub 3 1 roll exch xadrht leadjust add add exch\n",
  226. "yadtop leadjust add add /outflag 0 def /xadlft 0 def /yadbot 0 def\n",
  227. "/xadrht 0 def /yadtop 0 def}if}bind def /leadjust{(m)stringwidth pop .5\n",
  228. "mul}bind def /Mrotcheck{dup 90 eq{yadbot /yadbot xadrht def /xadrht\n",
  229. "yadtop def /yadtop xadlft def /xadlft exch def}if dup cos 1 index sin\n",
  230. "Checkaux dup cos 1 index sin neg exch Checkaux 3 1 roll pop pop}bind def\n",
  231. "/Checkaux{4 index exch 4 index mul 3 1 roll mul add 4 1 roll}bind def\n",
  232. "/Mboxrot{Mrot 90 eq{brotaux 4 2 roll}if Mrot 180 eq{4 2 roll brotaux 4 2\n",
  233. "roll brotaux}if Mrot 270 eq{4 2 roll brotaux}if}bind def /brotaux{neg\n",
  234. "exch neg}bind def /Mabsproc{0 matrix defaultmatrix dtransform\n",
  235. "idtransform dup mul exch dup mul add sqrt}bind def /Mabswid{Mabsproc\n",
  236. "setlinewidth}bind def /Mabsdash{exch[exch{Mabsproc}forall]exch setdash}\n",
  237. "bind def /MBeginOrig{Momatrix concat}bind def /MEndOrig{Mgmatrix\n",
  238. "setmatrix}bind def /sampledsound where{pop}{/sampledsound{exch pop exch\n",
  239. "5 1 roll mul 4 idiv mul 2 idiv exch pop exch /Mtempproc exch def{\n",
  240. "Mtempproc pop}repeat}bind def}ifelse /g{setgray}bind def /k{\n",
  241. "setcmykcolor}bind def /m{moveto}bind def /p{gsave}bind def /r{\n",
  242. "setrgbcolor}bind def /w{setlinewidth}bind def /C{curveto}bind def /F{\n",
  243. "fill}bind def /L{lineto}bind def /P{grestore}bind def /s{stroke}bind def\n",
  244. "/setcmykcolor where{pop}{/setcmykcolor{4 1 roll[4 1 roll]{1 index sub 1\n",
  245. "sub neg dup 0 lt{pop 0}if dup 1 gt{pop 1}if exch}forall pop setrgbcolor}\n",
  246. "bind def}ifelse /Mcharproc{currentfile(x)readhexstring pop 0 get exch\n",
  247. "div}bind def /Mshadeproc{dup 3 1 roll{dup Mcharproc 3 1 roll}repeat 1 eq\n",
  248. "{setgray}{3 eq{setrgbcolor}{setcmykcolor}ifelse}ifelse}bind def\n",
  249. "/Mrectproc{3 index 2 index moveto 2 index 3 -1 roll lineto dup 3 1 roll\n",
  250. "lineto lineto fill}bind def /Mcolorimage{7 1 roll pop pop matrix\n",
  251. "invertmatrix concat 2 exch exp 1 sub 3 1 roll 1 1 2 index{1 1 4 index{\n",
  252. "dup 1 sub exch 2 index dup 1 sub exch 7 index 9 index Mshadeproc\n",
  253. "Mrectproc}for pop}for pop pop pop pop}bind def /Mimage{pop matrix\n",
  254. "invertmatrix concat 2 exch exp 1 sub 3 1 roll 1 1 2 index{1 1 4 index{\n",
  255. "dup 1 sub exch 2 index dup 1 sub exch 7 index Mcharproc setgray\n",
  256. "Mrectproc}for pop}for pop pop pop}bind def\n",
  257. "" };
  258.  
  259. void main(argc,argv)
  260. int argc;
  261. char *argv[];
  262. {
  263.     float width = 161.0;         /* Picture width in bp */
  264.     float height = 100.0;        /* Picture height in bp */
  265.     float aspectratio = 0.61803; /* MMA aspect ratio */
  266.     float convfactor;            /* conversion factor from bp to a TeX's unit */
  267.     float oldoffx,oldoffy;
  268.     float newoffx,newoffy;
  269.     float addoffx,addoffy;
  270.     bool widthchoosen = FALSE;   /* the width has been choosen ? */
  271.     bool heightchoosen = FALSE;  /* the height has been choosen ? */
  272.     bool enclosemath = TRUE;     /* enclose MMA strings in $...$ ? */
  273.     bool addfbox = FALSE;        /* enclose the picture into an \fbox ? */
  274.     bool addfontsize = FALSE;    /* change default font size ? */
  275.     bool nofnameout = TRUE;      /* output filename specified ? */
  276.     bool substbboffs = FALSE;    /* substitute text bb offsets ? */
  277.     bool includeprolog = FALSE;  /* include the PostScript prolog ? */
  278.     bool whitebg = FALSE;        /* white background in mmaputtex ? */
  279.     bool allocfnameout = FALSE;
  280.     struct scaletrasl st,mat;
  281.     int i,j,k,nfilein=0;
  282.     char *fnamein[NMAXFILEIN];
  283.     char *fnameout="";
  284.     char *fboxsep="0pt";
  285.     char *fontsize="";
  286.     char *outunit="bp";
  287.     char tmpunit1[3],tmpunit2[3];
  288.     FILE *filein,*fileout,*filetex;
  289.     long tc;        /* for time/date */
  290.     struct tm *tp;  /* for time/date */
  291.  
  292.     if ((p=malloc(sizeof(struct pnts)*NMAX)) == NULL) {
  293.         printf("Error: not enough memory\n");
  294.         exit(1);
  295.     }
  296.  
  297.     printf("mma2ltx v1.2 - Copyright (C) 1994 Giuseppe Ghibo`\n");
  298.  
  299. /* scan options */
  300.     for (i=1; i<argc; i++) {
  301.         if (*argv[i]==OPTSWITCH1 || *argv[i]=='/') {
  302.             char *s = argv[i] + 2; /* skip next char */
  303.             char opt = argv[i][1]; /* option string */
  304.  
  305.             switch (opt) {
  306.             case 'w': case 'W':
  307.                 if (*s=='\0' && argv[i+1])
  308.                     s=argv[++i];
  309.                 width=strtobp(s);
  310.                 widthchoosen = TRUE; /* a width has been choosen */
  311.                 break;
  312.  
  313.             case 'h': case 'H':
  314.                 if (*s=='\0' && argv[i+1])
  315.                     s=argv[++i];
  316.                 height=strtobp(s);
  317.                 heightchoosen = TRUE; /* an height has been choosen */
  318.                 break;
  319.  
  320.             case 'd': case 'D':
  321.                 Mnodistort = FALSE;
  322.                 break;
  323.  
  324.             case '?':
  325.                 printf("Usage: mma2ltx [<options>] <filename(s)> [<options>]\n");
  326.                 printf("Where <options> is one or more of:\n\n");
  327.                 printf("\t  -?  Show these messages\n");
  328.                 printf("\t  -d  Don't keep the aspect ratio\n");
  329.                 printf("\t  -n  Deactivate automatic $...$ enclosing\n");
  330.                 printf("\t  -p  Include the Mathematica PostScript prologue in the .EPS file\n");
  331.                 printf("\t  -b  Enclose every string into a white box (default = transpar. box)\n");
  332.                 printf("\t  -h<dimen> Set picture height to <dimen> (default = 100bp)\n");
  333.                  printf("\t  -w<dimen> Set picture width  to <dimen> (default = 161bp)\n");
  334.                 printf("\t  -f<dimen> Add an \\fbox to the picture (\\fboxsep=<dimen>)\n");
  335.                 printf("\t  -u<unit>  Set all dimensions in the unit <unit>\n");
  336.                 printf("\t  -s<cmd>   Set the font size with the TeX command <cmd>\n");
  337.                 printf("\t  -o<filename> Output filename\n");
  338.                 printf("\t  -c(sx,sy)=(newsx,newsy)(<dimen>,<dimen>) (change alignment)\n\n");
  339.                 printf("\t  <dimen> = a number followed by one of TeX's unit (e.g. 10.3cm)\n");
  340.                 printf("\t  <unit>  = a TeX's unit (e.g. cm)\n");
  341.                 printf("\t  <cmd>   = a TeX command without the backslash '\\'\n\n");
  342.                 printf("Example:\n");
  343.                 printf("\t mma2ltx -sfootnotesize -w5in pic1.ps pic2.ps\n");
  344.                                 printf("process the files `pic1.ps' and `pic2.ps'. The width of the pictures\n");
  345.                                 printf("will be 5 inch and \\footnotesize will be used as LaTeX command to\n");
  346.                                 printf("set the pictures font size.\n");
  347.                 exit(1);
  348.  
  349.             case 'n': case 'N':
  350.                 enclosemath = FALSE;
  351.                 break;
  352.  
  353.             case 'o': case 'O':
  354.                 if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1)
  355.                     s = argv[++i];
  356.                 fnameout = s;
  357.                 nofnameout = FALSE;
  358.                 break;
  359.  
  360.             case 's': case 'S':
  361.                 if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1)
  362.                     s = argv[++i];
  363.                 addfontsize = TRUE;
  364.                 if (*s != '\0')
  365.                     fontsize = s;
  366.                 break;
  367.  
  368.             case 'f': case 'F':
  369.                 if (*s == '\0' && argv[i+1] && *argv[i+1] != OPTSWITCH1)
  370.                     s = argv[++i];
  371.                 addfbox = TRUE;
  372.                 if (*s != '\0')
  373.                     fboxsep = s;
  374.                 break;
  375.             
  376.             case 'u': case 'U':
  377.                 if (*s=='\0' && argv[i+1])
  378.                     s=argv[++i];
  379.                 sscanf(s,"%2s",outunit);
  380.                 break;
  381.  
  382.             case 'c': case 'C':
  383.                 if (*s=='\0' && argv[i+1])
  384.                     s=argv[++i];
  385.                 k=sscanf(s,"(%f,%f)=(%f,%f)(%f%2s,%f%2s)",
  386.                     &oldoffx,&oldoffy,&newoffx,&newoffy,
  387.                     &addoffx,tmpunit1,&addoffy,tmpunit2);
  388.                 if (k != 8) {
  389.                     printf("Error, option '-c': bad argument!\n");
  390.                     exit(1);
  391.                 }
  392.                 sprintf(tmpbuf1,"%f%2s",addoffx,tmpunit1);
  393.                 sprintf(tmpbuf2,"%f%2s",addoffy,tmpunit2);
  394.                 addoffx = strtobp(tmpbuf1);
  395.                 addoffy = strtobp(tmpbuf2);
  396.                 substbboffs = TRUE;
  397.                 break;
  398.  
  399.             case 'p': case 'P':
  400.                 includeprolog = TRUE;
  401.                 break;
  402.  
  403.             case 'b': case 'B':
  404.                 whitebg = TRUE;
  405.                 break;
  406.  
  407.             default:
  408.                 break;
  409.             }
  410.         }
  411.         else {
  412.             if (nfilein >= NMAXFILEIN) {
  413.                 printf("Error: I can't process more than %d files.\n",NMAXFILEIN);
  414.                 exit(1);
  415.             }
  416.             else
  417.                 fnamein[nfilein++]=argv[i];
  418.         }
  419.     }
  420.  
  421.     if (nfilein == 0) {
  422.         printf("Error: You must specify at least one filename!\n");
  423.         exit(1);
  424.     }
  425.  
  426.     if (nfilein > 1 && !nofnameout) {
  427.         printf("Error: You can't specify the output name when process multiple files\n");
  428.         exit(1);
  429.     }
  430.  
  431. for (j=0 ; j < nfilein ; j++) {
  432.     if ((filein=fopen(fnamein[j],"r")) == NULL) {
  433.         printf("Error: Can't open file '%s' (r)\n",fnamein[j]);
  434.         printf("%s\n",strerror(errno));
  435.         exit(1);
  436.     }
  437.  
  438.     if (*fnameout == '\0' || nofnameout) {
  439.         stripext(tmpbuf1,fnamein[j]);
  440.         strcat(tmpbuf1,".eps");
  441.         if (allocfnameout)
  442.             free(fnameout);
  443.         if ((fnameout=malloc(strlen(tmpbuf1)+1)) == NULL) {
  444.             printf("Error: Not enough memory!\n");
  445.             exit(1);
  446.         }
  447.         allocfnameout = TRUE;
  448.         strcpy(fnameout,tmpbuf1);
  449.     }
  450.  
  451.     if ((fileout=fopen(fnameout,"w")) == NULL) {
  452.         printf("Error: Can't open file '%s' (w)\n",fnameout);
  453.         printf("%s\n",strerror(errno));
  454.         exit(1);
  455.     }
  456.  
  457. /* search aspect ratio */
  458.     while ((fgets(tmpbuf1,TMPLEN,filein) != NULL)) {
  459.         if ((sscanf(tmpbuf1,"%%%%AspectRatio: %f",&aspectratio)) == 1) {
  460.             break;
  461.         }        
  462.     }
  463.  
  464.     mat.Ax = 0.0;
  465.     mat.Ay = 0.0;
  466.     mat.Bx = 0.0;
  467.     mat.By = 0.0;
  468.  
  469. /* get transformation matrix */
  470.     while ((fgets(tmpbuf1,TMPLEN,filein) != NULL)) {
  471.         if ((strstr(tmpbuf1,"Scaling calc")) != NULL) {
  472.             fgets(tmpbuf1,TMPLEN,filein);
  473.             sscanf(tmpbuf1,"%f %f %f %f [",&mat.Bx,&mat.Ax,&mat.By,&mat.Ay);
  474.             break;
  475.         }
  476.     }
  477.  
  478. /* get size */
  479.     np = 0;
  480.     while ((fgets(tmpbuf1,TMPLEN,filein) != NULL) && (np < NMAX)) {
  481.         float gx,gy,tx,ty;
  482.         if ((strstr(tmpbuf1,"] MathSca")) != NULL)
  483.             break;
  484.         if ((sscanf(tmpbuf1,"[ %f %f %f %f ]",&gx,&gy,&tx,&ty)) == 4) {
  485.             p[np].gx = gx;
  486.             p[np].gy = gy;
  487.             p[np].tx = tx;
  488.             p[np++].ty = ty;
  489.         }
  490.     }
  491.  
  492.     stripext(texfname,fnameout);
  493.     strcat(texfname,".tex");
  494.  
  495.     if ((filetex=fopen(texfname,"w")) == NULL) {
  496.         printf("Error: Can't open file '%s' (w)\n",texfname);
  497.         printf("%s\n",strerror(errno));
  498.         exit(1);
  499.     }
  500.     rewind(filein);
  501.  
  502. /* compute new scale factor */
  503.     if (widthchoosen && !heightchoosen)
  504.         height = width * aspectratio;
  505.     else if (heightchoosen && !widthchoosen)
  506.         width = height / aspectratio;
  507.  
  508.     if (np < 2) {
  509.         p[0].gx = -0.001;
  510.         p[0].gy = -0.001;
  511.         p[0].tx = 0.0;
  512.         p[0].ty = 0.0;
  513.         p[1].gx = 1.001;
  514.         p[1].gy = 0.61903;
  515.         p[1].tx = 0.0;
  516.         p[1].ty = 0.0;
  517.         np = 2;
  518.     }
  519.     Mlp(width,height,&st);
  520.  
  521. /* Prepare PostScript file */
  522.     fprintf(fileout,"%%!PS-Adobe-2.0 EPSF-2.0\n");
  523.     fprintf(fileout,"%%%%BoundingBox: 0 0 %.2f %.2f\n",width,height);
  524.     fprintf(fileout,"%%%%Title: %s\n",fnameout);
  525.     fprintf(fileout,"%%%%Creator: mma2ltx v1.2\n");
  526.     time(&tc); /* get current time */
  527.     tp = localtime(&tc);
  528.     fprintf(fileout,"%%%%CreationDate: %s",asctime(tp));
  529.     fprintf(fileout,"%%%%EndComments\n");
  530.     fprintf(fileout,"%%MMA2LTXCommandLine: ");
  531.     for (i=0;i<argc;i++) fprintf(fileout,"%s ",argv[i]);
  532.     fprintf(fileout,"\n");
  533.     if (!includeprolog) {
  534.         fprintf(fileout,"%%MMA2LTXComment: For use with Mathematica prologue '%s'\n",PROLOG);
  535.     }
  536.     else {
  537.         fprintf(fileout,"%%%%BeginProcSet: %s\n",PROLOG);
  538.         fprintf(fileout,"%% Mathematica v2.2 prologue\n");
  539.         fprintf(fileout,"/Mathdict 150 dict def\n");
  540.     }
  541.     fprintf(fileout,"Mathdict begin\n");
  542.     fprintf(fileout,"/Mwidth %.2f def\n",width);
  543.     fprintf(fileout,"/Mheight %.2f def\n",height);
  544.     fprintf(fileout,"/Mnodistort %s def\n",(Mnodistort ? "true" : "false"));
  545.     if (includeprolog) {
  546.         int k=0;
  547.         while (prologue[k][0] != '\0') {
  548.             fputs(prologue[k++],fileout);
  549.         }
  550.         fprintf(fileout,"%%%%EndProcSet: %s\n",PROLOG);
  551.     }
  552.     fprintf(fileout,"%%MMA2LTXComment: Here follow the original Mathematica file stripped of the text strings\n");
  553.  
  554. /* Prepare TeX file */
  555.     fprintf(filetex,"%% Picture: %s\n",fnameout);
  556.     fprintf(filetex,"%% Created by mma2ltx v1.2 - Copyright (C) 1994 Giuseppe Ghib\\`o\n");
  557.     fprintf(filetex,"%% Command line : ");
  558.     for (i=0;i<argc;i++) fprintf(filetex,"%s ",argv[i]);
  559.     fprintf(filetex,"\n");
  560.     fprintf(filetex,"%% Creation date: %s",asctime(tp));
  561.  
  562.     convfactor = bptounit(outunit); /* set convfactor */
  563.  
  564.     if (includeprolog) /* don't use \special{header=texmma??.pro} */
  565.         fprintf(filetex,"\\mmaheaderprofalse\n");
  566.         else               /* use \special{header=texmma??.pro} */
  567.         fprintf(filetex,"\\mmaheaderprotrue\n");
  568.  
  569.     fprintf(filetex,"\173%%\n"); /* left bracket */
  570.  
  571.     if (addfontsize)
  572.         fprintf(filetex,"\\%s%%\n",fontsize);
  573.  
  574.     if (addfbox) {
  575.         fprintf(filetex,"\\fboxsep=%s%%\n",fboxsep);
  576.         fprintf(filetex,"\\fbox\173%%\n");
  577.     }
  578.  
  579.     fprintf(filetex,"\\mmasetpic(%.4f,%.4f)[%2s]\173%s\175\n",
  580.         width/convfactor,height/convfactor,outunit,fnameout);
  581.  
  582. /* Scan #1 of Mathematica PostScript file, for text fits */
  583.     while ((fgets(tmpbuf1,TMPLEN,filein) != NULL)) {
  584.         float x,y,gx,gy,offx,offy;
  585.         if ((strstr(tmpbuf1,"Mshowa")) != NULL) {
  586.             char *s1=tmpbuf1;
  587.             char *s2=tmpbuf2;
  588.             while (*s1) {
  589.                 if (*s1 == '[' && *(s1+1) == '(') s1 += 2;
  590.                 if (*s1 == ')' && *(s1+1) == ']') {
  591.                     s1 += 2;
  592.                     break;
  593.                 }
  594.                 if (*s1 == '\\')
  595.                     if (*(s1+1) == '(' || *(s1+1) == ')'
  596.                         || *(s1+1) == '\\') s1++;
  597.                 *s2++ = *s1++;
  598.             }
  599.             *s2 = '\0';
  600.             sscanf(s1,"%f %f %f %f\n",&gx,&gy,&offx,&offy);
  601.             x = st.Ax * gx + st.Bx;
  602.             y = st.Ay * gy + st.By;
  603.             if (substbboffs && (offx == oldoffx || offy == oldoffy)) {
  604.                 fprintf(filetex,"\\mmatextfits(%.3f,%.3f)(%g,%g)(%g,%g)\173%s%s%s\175\n",
  605.                     x/convfactor,y/convfactor,newoffx,newoffy,
  606.                     addoffx/convfactor,addoffy/convfactor,(enclosemath ? "$" : ""),
  607.                     tmpbuf2,(enclosemath ? "$" : ""));
  608.                 continue;
  609.             }
  610.             else {
  611.                 fprintf(filetex,"\\mmatextfits(%.3f,%.3f)(%g,%g)\173%s%s%s\175\n",
  612.                     x/convfactor,y/convfactor,offx,offy,(enclosemath ? "$" : ""),
  613.                     tmpbuf2,(enclosemath ? "$" : ""));
  614.                 continue;
  615.             }
  616.         }
  617.         if ((strstr(tmpbuf1,"Msboxa")) != NULL || (strstr(tmpbuf1,"Mshowa")) != NULL)
  618.              continue;
  619.         else
  620.             fputs(tmpbuf1,fileout);
  621.     }
  622.  
  623.     fprintf(fileout,"end\n"); /* appending end Mathdict */
  624.     fclose(fileout);
  625.     rewind(filein);
  626.  
  627. /* Scan #2 of Mathematica PostScript file to put text */
  628.     fprintf(filetex,"\\begin{mmapicture}\n");
  629.     while ((fgets(tmpbuf1,TMPLEN,filein) != NULL)) {
  630.         float x,y,gx,gy,offx,offy;
  631.         if ((strstr(tmpbuf1,"Mshowa")) != NULL) {
  632.             char *s1=tmpbuf1;
  633.             char *s2=tmpbuf2;
  634.             while (*s1) {
  635.                 if (*s1 == '[' && *(s1+1) == '(') s1 += 2;
  636.                 if (*s1 == ')' && *(s1+1) == ']') {
  637.                     s1 += 2;
  638.                     break;
  639.                 }
  640.                 if (*s1 == '\\')
  641.                     if (*(s1+1) == '(' || *(s1+1) == ')'
  642.                         || *(s1+1) == '\\') s1++;
  643.                 *s2++ = *s1++;
  644.             }
  645.             *s2 = '\0';
  646.             sscanf(s1,"%f %f %f %f\n",&gx,&gy,&offx,&offy);
  647.             x = st.Ax * gx + st.Bx;
  648.             y = st.Ay * gy + st.By;
  649.             if (substbboffs && (offx == oldoffx || offy == oldoffy)) {
  650.                 fprintf(filetex,"\\mmaputtext%s(%.3f,%.3f)(%g,%g)(%g,%g)\173%s%s%s\175\n",
  651.                     (whitebg ? "*" : ""), x/convfactor,y/convfactor,newoffx,newoffy,
  652.                     addoffx/convfactor,addoffy/convfactor,(enclosemath ? "$" : ""),
  653.                     tmpbuf2,(enclosemath ? "$" : ""));
  654.                 continue;
  655.             }
  656.             else {
  657.                 fprintf(filetex,"\\mmaputtext%s(%.3f,%.3f)(%g,%g)\173%s%s%s\175\n",
  658.                     (whitebg ? "*" : ""), x/convfactor,y/convfactor,offx,offy,(enclosemath ? "$" : ""),
  659.                     tmpbuf2,(enclosemath ? "$" : ""));
  660.                 continue;
  661.             }
  662.         }
  663.     }
  664.  
  665.     fprintf(filetex,"\\end{mmapicture}%s%%\n",(addfbox ? "\175" : ""));
  666.     fprintf(filetex,"\175%%\n"); /* right bracket */
  667.  
  668.     fclose(filetex);
  669.     fclose(filein);
  670.  
  671.     printf("picture '%s' processed.\n",fnamein[j]);
  672.     printf("width=%g%s height=%g%s\n\n",width/convfactor,outunit,
  673.         height/convfactor,outunit);
  674.  
  675.     }
  676.  
  677.     free(p);
  678.     if (allocfnameout)
  679.          free(fnameout);
  680. }
  681.  
  682. void Mlp(float sx, float sy, struct scaletrasl *st)
  683. {
  684.     struct cw cw;
  685.     bool xok,yok;
  686.     float Anew,Bnew;
  687.  
  688.     st->Ax = sx/(p[np-1].gx - p[np-2].gx);
  689.     st->Ay = sy/(p[np-1].gy - p[np-2].gy);
  690.     st->Bx = 0.0;
  691.     st->By = 0.0;
  692.     while (1) {
  693.         if (Mnodistort) st->Ax = st->Ay = min(st->Ax,st->Ay);
  694.         Mlprun(st->Ax,st->Ay,&cw);
  695.         Mlp1(sx,st->Ax,cw.ctx,cw.wtx,cw.cgx,cw.wgx,&Anew,&Bnew,&xok);
  696.         st->Ax = Anew;
  697.         st->Bx = Bnew;
  698.         Mlp1(sy,st->Ay,cw.cty,cw.wty,cw.cgy,cw.wgy,&Anew,&Bnew,&yok);
  699.         st->Ay = Anew;
  700.         st->By = Bnew;
  701.         if (xok && yok) break;
  702.     }    
  703. }
  704.  
  705.  
  706. void Mlprun(float Ax, float Ay, struct cw *cw)
  707. {
  708.     struct pnts low,high;
  709.     float rx1,rx2,ry1,ry2;
  710.     int i;
  711.  
  712.     low.gx = high.gx = p[0].gx;
  713.     low.gy = high.gy = p[0].gy;
  714.     low.tx = high.tx = p[0].tx;
  715.     low.ty = high.ty = p[0].ty;
  716.  
  717.     for (i=0; i<np; i++) {
  718.         rx1 = p[i].gx * Ax + p[i].tx;
  719.         ry1 = p[i].gy * Ay + p[i].ty;
  720. /* get low */
  721.         rx2 = low.gx * Ax + low.tx;
  722.         ry2 = low.gy * Ay + low.ty;
  723.         if (rx1 < rx2) {
  724.             low.gx = p[i].gx;
  725.             low.tx = p[i].tx;
  726.         }
  727.         if (ry1 < ry2) {
  728.             low.gy = p[i].gy;
  729.             low.ty = p[i].ty;
  730.         }
  731. /* get high */
  732.         rx2 = high.gx * Ax + high.tx;
  733.         ry2 = high.gy * Ay + high.ty;
  734.         if (rx1 > rx2) {
  735.             high.gx = p[i].gx;
  736.             high.tx = p[i].tx;
  737.         }
  738.         if (ry1 > ry2) {
  739.             high.gy = p[i].gy;
  740.             high.ty = p[i].ty;
  741.         }
  742.     }
  743.     cw->ctx = (low.tx + high.tx)/2.0;
  744.     cw->wtx = high.tx - low.tx;
  745.     cw->cgx = (low.gx + high.gx)/2.0;
  746.     cw->wgx = high.gx - low.gx;
  747.     cw->cty = (low.ty + high.ty)/2.0;
  748.     cw->wty = high.ty - low.ty;
  749.     cw->cgy = (low.gy + high.gy)/2.0;
  750.     cw->wgy = high.gy - low.gy;
  751. }
  752.  
  753. void Mlp1(float s,float A,float ct,float wt,float cg,float wg,float *Anew,float *B,bool *done)
  754. {
  755.     *Anew = A;
  756.     *done = TRUE;
  757.  
  758.     if ((A*wg) >= (s-wt)) {
  759.         *Anew = (s-wt)/wg*0.99999;
  760.         *done = FALSE;
  761.     }
  762.     *B = s/2.0 - ct - (*Anew) * cg;
  763. }
  764.  
  765. /* converts TeX units to bp */
  766. float strtobp(char *s)
  767. {
  768.     char unit[3];
  769.     float value;
  770.     struct TeXunits *t;
  771.  
  772.     if (*s == ':' || *s == '=') s++;
  773.     sscanf(s,"%f%2s",&value,unit);
  774.     for (t=TeXtable; *(t->strunit) != '\0'; t++) {
  775.         if (strcmp(strtolwr(unit),t->strunit) == 0) {
  776.             value *= t->convfactor;
  777.             break;
  778.         }
  779.     }
  780.     return(value);
  781. }
  782.  
  783. /* converts bp to TeX units */
  784. float bptounit(char *unit)
  785. {
  786.     struct TeXunits *t;
  787.  
  788.     for (t=TeXtable; *(t->strunit) != '\0'; t++) {
  789.         if (strcmp(strtolwr(unit),t->strunit) == 0)
  790.             return (t->convfactor);
  791.     }
  792.     return(1.0);
  793. }
  794.  
  795. /* remove the extension from a filename */
  796. void stripext(char *to, char *from)
  797. {
  798.     while (*from) {
  799.         if (*from == '.')
  800.             break;
  801.         *to++ = *from++;
  802.     }
  803.     *to = '\0';
  804. }
  805.  
  806. /* convert a string to lowercase */
  807. char *strtolwr(char *str)
  808. {
  809.     register char *p=str;
  810.  
  811.     while (*p++)
  812.         *p = (char) tolower((int) *p);
  813.  
  814.     return (str);
  815. }
  816.